﻿%define pg.RootNamespace ParserGenerator
%define pg.SyntacticAnalysisNamespace ParserGenerator.Languages.CSharp
%define pg.SourceContextNamespace ParserGenerator.Input
%define pg.OutputNamespace ParserGenerator.Output

%define pg.AllowAutoDefineLiteralTokens False
%define pg.UsePythonLikeIndentation False
%define pg.indented False

%define pg.parser.classname CSharpProgramParser
%define pg.parser.namespace ParserGenerator.Languages.CSharp

%define pg.parser.usings (
    ParserGenerator.Collections,
)

%keyword KeywordAbstract ('abstract')
%keyword KeywordAs ('as')
%keyword KeywordBase ('base')
%keyword KeywordBool ('bool')
%keyword KeywordBreak ('break')
%keyword KeywordByte ('byte')
%keyword KeywordCase ('case')
%keyword KeywordCatch ('catch')
%keyword KeywordChar ('char')
%keyword KeywordChecked ('checked')
%keyword KeywordClass ('class')
%keyword KeywordConst ('const')
%keyword KeywordContinue ('continue')
%keyword KeywordDecimal ('decimal')
%keyword KeywordDefault ('default')
%keyword KeywordDelegate ('delegate')
%keyword KeywordDo ('do')
%keyword KeywordDouble ('double')
%keyword KeywordElse ('else')
%keyword KeywordEnum ('enum')
%keyword KeywordEvent ('event')
%keyword KeywordExplicit ('explicit')
%keyword KeywordExtern ('extern')
%keyword KeywordFalse ('false')
%keyword KeywordFinally ('finally')
%keyword KeywordFixed ('fixed')
%keyword KeywordFloat ('float')
%keyword KeywordFor ('for')
%keyword KeywordForeach ('foreach')
%keyword KeywordGoto ('goto')
%keyword KeywordIf ('if')
%keyword KeywordImplicit ('implicit')
%keyword KeywordIn ('in')
%keyword KeywordInt ('int')
%keyword KeywordInterface ('interface')
%keyword KeywordInternal ('internal')
%keyword KeywordIs ('is')
%keyword KeywordLock ('lock')
%keyword KeywordLong ('long')
%keyword KeywordNamespace ('namespace')
%keyword KeywordNew ('new')
%keyword KeywordNull ('null')
%keyword KeywordObject ('object')
%keyword KeywordOperator ('operator')
%keyword KeywordOut ('out')
%keyword KeywordOverride ('override')
%keyword KeywordParams ('params')
%keyword KeywordPrivate ('private')
%keyword KeywordProtected ('protected')
%keyword KeywordPublic ('public')
%keyword KeywordReadonly ('readonly')
%keyword KeywordRef ('ref')
%keyword KeywordReturn ('return')
%keyword KeywordSbyte ('sbyte')
%keyword KeywordSealed ('sealed')
%keyword KeywordShort ('short')
%keyword KeywordSizeof ('sizeof')
%keyword KeywordStackalloc ('stackalloc')
%keyword KeywordStatic ('static')
%keyword KeywordString ('string')
%keyword KeywordStruct ('struct')
%keyword KeywordSwitch ('switch')
%keyword KeywordThis ('this')
%keyword KeywordThrow ('throw')
%keyword KeywordTrue ('true')
%keyword KeywordTry ('try')
%keyword KeywordTypeof ('typeof')
%keyword KeywordUint ('uint')
%keyword KeywordUlong ('ulong')
%keyword KeywordUnchecked ('unchecked')
%keyword KeywordUnsafe ('unsafe')
%keyword KeywordUshort ('ushort')
%keyword KeywordUsing ('using')
%keyword KeywordVirtual ('virtual')
%keyword KeywordVoid ('void')
%keyword KeywordVolatile ('volatile')
%keyword KeywordWhile ('while')

# TODO: fix
#%contextual KeywordDynamic ('dynamic') : Identifier
%token Identifier ("identifier") : Identifier
Identifier = (name : string)

IntegerTypeSuffix: one of
    U u L l UL Ul uL ul LU Lu lU lu
FloatTypeSuffix: one of
    F f
DoubleTypeSuffix: one of
    D d
DecimalTypeSuffix: one of
    M m
Literal:
    Boolean (value : bool)
    Integer (value : global::System.Numerics.BigInteger, isHexadecimal : bool?, suffix : IntegerTypeSuffix?)
    Real:
        Float (value : float, suffix : FloatTypeSuffix?)
        Double (value : double, suffix : DoubleTypeSuffix?)
        Decimal (value : decimal, suffix : DecimalTypeSuffix?)
    Character (value : char16)
    String (value : string, isVerbatim : bool?)
    Null

# P492 B.2.1 Basic concepts

NamespaceName = (name : NamespaceOrTypeName)
TypeName = (name : NamespaceOrTypeName)
NamespaceOrTypeName:
    Unqualified (name : Identifier, typeArguments : TypeArgumentList?)
    Qualified (operand : NamespaceOrTypeName, name : Identifier, typeArguments : TypeArgumentList?)
    QualifiedAliasMember (member : QualifiedAliasMember)

# P492 B.2.2 Types

Type:
    Value:
        Struct:
            NamedStruct (name : TypeName)
            Simple:
                Numeric:
                    Integral:
                        SByte
                        Byte
                        Short
                        UShort
                        Int
                        UInt
                        Long
                        ULong
                        Char
                    FloatingPoint:
                        Float
                        Double
                    Decimal
                Bool
            Nullable (operand : NonNullableValueType)
        Enum (name : TypeName)
    Reference:
        Class:
            NamedClass (name : TypeName)
            Object
            Dynamic
            String
        Interface (name : TypeName)
        Array (elementType : NonArrayType, rank : RankSpecifiers)
        Delegate (name : TypeName)
    TypeParameter (name : Identifier)
NonNullableValueType = (`type` : Type)
NonArrayType = (`type` : Type)
TypeArgumentList = (arguments : TypeArguments)
TypeArguments = (items : [TypeArgument]+)
TypeArgument = (`type` : Type)

# P494 B.2.3 Variables

VariableReference = (variable : Expression)

# P494 B.2.4 Expressions

ArgumentList = (items : [Argument]+)
Argument = (name : ArgumentName?, value : ArgumentValue)
ArgumentName = (name : Identifier)
ArgumentValue:
    In (value : Expression)
    Ref (value : VariableReference)
    Out (value : VariableReference)
Expression:
    NonAssignment:
        Unary:
            Primary:
                PrimaryNoArrayCreation:
                    Literal (value : Literal)
                    # TODO: implement interpolated_string_expression
                    SimpleName (name : SimpleName)
                    Parenthesized (operand : Expression)
                    BlockComment (content : string)
                    MemberAccess:
                        ObjectMemberAccess (operand : Expression, member : Identifier, typeArguments : TypeArgumentList?)
                        NullableObjectMemberAccess (operand : Expression, member : Identifier, typeArguments : TypeArgumentList?)
                        PredefinedTypeMemberAccess (operand : PredefinedType, member : Identifier, typeArguments : TypeArgumentList?)
                        QualifiedAliasMemberAccess (operand : QualifiedAliasMember, member : Identifier)
                    Invocation (operand : Expression, arguments : ArgumentList?)
                    ElementAccess (operand : PrimaryNoArrayCreationExpression, arguments : ExpressionList)
                    ThisAccess
                    BaseAccess:
                        BaseMemberAccess (member : Identifier)
                        BaseElementAccess (arguments : ExpressionList)
                    PostIncrement (operand : Expression)
                    PostDecrement (operand : Expression)
                    ObjectCreation (`type` : Type, arguments : ArgumentList?, initializer : ObjectOrCollectionInitializer?)
                    ObjectCreateionWithInitializer (`type` : Type, initializer : ObjectOrCollectionInitializer)
                    DelegateCreation (`type` : DelegateType, argument : Expression)
                    AnonymousObjectCreation (initializer : AnonymousObjectInitializer)
                    ValueTupleCreation (arguments : ExpressionList)
                    Typeof (`type` : Type)
                    UnboundTypeof (`type` : UnboundTypeName)
                    VoidTypeof
                    Checked (operand : Expression)
                    Unchecked (operand : Expression)
                    DefaultValue (`type` : Type)
                    Nameof (entity : NamedEntity)
                    AnonymousMethod (signature : ExplicitAnonymousFunctionSignature?, body : Block)
                ArrayCreation:
                    ArrayCreationWithDimensions (elementType : NonArrayType, dimensions : ExpressionList, specifiers : RankSpecifiers?, initializer : ArrayInitializer?)
                    ArrayCreationWithArrayType (arrayType : ArrayType, initializer : ArrayInitializer)
                    ArrayCreationWithRankSpecifier (specifier : RankSpecifier, initializer : ArrayInitializer)
            Positive (operand : Expression)
            Negative (operand : Expression)
            LogicalNot (operand : Expression)
            BitwiseNot (operand : Expression)
            PreIncrement (operand : Expression)
            PreDecrement (operand : Expression)
            Cast (`type` : Type, operand : Expression)
            Await (operand : Expression)
        Binary:
            Multiply (left : Expression, right : Expression)
            Divide (left : Expression, right : Expression)
            Modulo (left : Expression, right : Expression)
            Add (left : Expression, right : Expression)
            Subtract (left : Expression, right : Expression)
            LeftShift (left : Expression, right : Expression)
            RightShift (left : Expression, right : Expression)
            LessThan (left : Expression, right : Expression)
            GreaterThan (left : Expression, right : Expression)
            LessEqual (left : Expression, right : Expression)
            GreaterEqual (left : Expression, right : Expression)
            IsInstanceOf (operand : Expression, `type` : Type)
            AsInstanceOf (operand : Expression, `type` : Type)
            EqualTo (left : Expression, right : Expression)
            NotEqualTo (left : Expression, right : Expression)
            BitwiseAnd (left : Expression, right : Expression)
            BitwiseXor (left : Expression, right : Expression)
            BitwiseOr (left : Expression, right : Expression)
            LogicalAnd (left : Expression, right : Expression)
            LogicalOr (left : Expression, right : Expression)
            NullCoalescing (left : Expression, right : Expression)
        Conditional (condition : Expression, truePart : Expression, falsePart : Expression)
        Lambda (signature : AnonymousFunctionSignature, body : AnonymousFunctionBody)
        Query (fromClause : FromClause, queryBody : QueryBody)
    Assignment (left : UnaryExpression, operator : AssignmentOperator, right : Expression)
SimpleName = (name : Identifier, typeArguments : TypeArgumentList?)
PredefinedType:
    SByte
    Byte
    Short
    UShort
    Int
    UInt
    Long
    ULong
    Char
    Float
    Double
    Decimal
    Bool
    Object
    String
ObjectOrCollectionInitializer:
    Object (value : ObjectInitializer)
    Collection (value : CollectionInitializer)
ObjectInitializer = (memberInitializers : MemberInitializerList?, hasTrailingComma : bool?)
MemberInitializerList = (items : [MemberInitializer]+)
MemberInitializer = (name : Identifier, value : InitializerValue)
InitializerValue:
    Member (value : Expression)
    ObjectOrCollection (value : ObjectOrCollectionInitializer)
CollectionInitializer = (elementInitializers : ElementInitializerList, hasTrailingComma : bool?)
ElementInitializerList = (items : [ElementInitializer]+)
ElementInitializer:
    Single (value : NonAssignmentExpression)
    Multiple (values : ExpressionList)
ExpressionList = (items : [Expression]+)
AnonymousObjectInitializer = (memberDeclarators : MemberDeclaratorList?, hasTrailingComma : bool?)
MemberDeclaratorList  = (items : [MemberDeclarator]+)
MemberDeclarator:
    SimpleName (name : SimpleName)
    MemberAccess (member : MemberAccessExpression)
    Binding (name : Identifier, value : Expression)
UnboundTypeName:
    Unqualified (name : Identifier, dimension : GenericDimensionSpecifier?)
    Qualified (operand : UnboundTypeName, name : Identifier, dimension : GenericDimensionSpecifier?)
    QualifiedAliasMember (member : UnboundQualifiedAliasMember)
UnboundQualifiedAliasMember = (scope : Identifier, member : Identifier, dimension : GenericDimensionSpecifier?)
GenericDimensionSpecifier = (dimension : int+)
NamedEntity:
    Simple (name : SimpleName)
    Qualified (target : NamedEntityTarget, member : Identifier, typeArguments : TypeArgumentList?)
NamedEntityTarget:
    This
    Base
    NamedEntity (entity : NamedEntity)
    PredefinedType (`type` : PredefinedType)
    QualifiedAliasMember (member : QualifiedAliasMember)
AnonymousFunctionSignature:
    Explicit (parameters : ExplicitAnonymousFunctionParameterList?)
    Implicit:
        FullImplicit (parameters : ImplicitAnonymousFunctionParameterList?)
        SimpleImplicit (parameter : ImplicitAnonymousFunctionParameter)
ExplicitAnonymousFunctionParameterList = (items : [ExplicitAnonymousFunctionParameter]+)
ExplicitAnonymousFunctionParameter = (
    modifier : ExplicitAnonymousFunctionParameterModifier?,
    `type` : Type,
    name : Identifier
)
ExplicitAnonymousFunctionParameterModifier:
    Ref
    Out
ImplicitAnonymousFunctionParameterList = (items : [ImplicitAnonymousFunctionParameter]+)
ImplicitAnonymousFunctionParameter = (name : Identifier)
AnonymousFunctionBody:
    Expression (expression : Expression)
    Block (block : Block)
FromClause = (`type` : Type?, enumerator : Identifier, enumerable : Expression)
QueryBody = (clauses : QueryBodyClauses?, selectOrGroup : SelectOrGroupClause, continuation : QueryContinuation?)
QueryBodyClauses = (items : [QueryBodyClause]+)
QueryBodyClause:
    From (clause : FromClause)
    Let (clause : LetClause)
    Where (clause : WhereClause)
    Join (clause : JoinClause)
    JoinInto (clause : JoinIntoClause)
    Orderby (clause : OrderbyClause)
LetClause = (name : Identifier, value : Expression)
WhereClause = (condition : BooleanExpression)
JoinClause = (
    `type` : Type?,
    name : Identifier,
    inOperand : Expression,
    onOperand : Expression,
    equalsOperand : Expression
)
JoinIntoClause = (
    `type` : Type?,
    name : Identifier,
    inOperand : Expression,
    onOperand : Expression,
    equalsOperand : Expression,
    target : Identifier
)
OrderbyClause = (orderings : Orderings)
Orderings = (items : [Ordering]+)
Ordering = (value : Expression, direction : OrderingDirection?)
OrderingDirection:
    Ascending
    Descending
SelectOrGroupClause:
    Select (clause : SelectClause)
    Group (clause : GroupClause)
SelectClause = (value : Expression)
GroupClause = (value : Expression, key : Expression)
QueryContinuation = (target : Identifier, queryBody : QueryBody)
AssignmentOperator:
    Assign
    MultiplyAssign
    DivideAssign
    ModuloAssign
    AddAssign
    SubtractAssign
    LeftShiftAssign
    RightShiftAssign
    BitwiseAndAssign
    BitwiseXorAssign
    BitwiseOrAssign
ConstantExpression = (value : Expression)
BooleanExpression = (value : Expression)

# P501 B.2.5 Statements

Statement:
    Labeled (label : Identifier, operand : Statement)
    Declaration:
        LocalVariableDeclaration (declaration : LocalVariableDeclaration)
        LocalConstantDeclaration (declaration : LocalConstantDeclaration)
    Embedded:
        Block (block : Block)
        Empty
        LineComment (content : string)
        Expression (expression : StatementExpression)
        Selection:
            If (condition : BooleanExpression, body : CompoundStatementBody, orElse : CompoundStatementBody?)
            Switch (value : Expression, body : SwitchBlock)
        Iteration:
            While (condition : BooleanExpression, body : CompoundStatementBody)
            Do (body : CompoundStatementBody, condition : BooleanExpression)
            For (initializer : ForInitializer?, condition : ForCondition?, iterator : ForIterator?, body : CompoundStatementBody)
            ForEach (`type` : LocalVariableType, enumerator : Identifier, enumerable : Expression, body : CompoundStatementBody)
        Jump:
            Break
            Continue
            Goto:
                GotoLabel (label : Identifier)
                GotoCase (value : ConstantExpression)
                GotoDefault
            Return (value : Expression?)
            Throw (value : Expression?)
        Try (body : Block, clauses : CatchClauseList)
        TryWithFinally (body : Block, clauses : CatchClauseList?, finallyClause : FinallyClause)
        Checked (body : Block)
        Unchecked (body : Block)
        Lock (value : Expression, body : CompoundStatementBody)
        Using (acquisition : ResourceAcquisition, body : CompoundStatementBody)
        Yield:
            YieldReturn (value : Expression)
            YieldBreak
CompoundStatementBody = (body : EmbeddedStatement)
Block = (statements : StatementList?)
StatementList = (items : [Statement]+)
LocalVariableDeclaration = (`type` : LocalVariableType, declarators : LocalVariableDeclarators)
LocalVariableType:
    Specific (`type` : Type)
    Var
LocalVariableDeclarators = (items : [LocalVariableDeclarator]+)
LocalVariableDeclarator = (name : Identifier, initializer : LocalVariableInitializer?)
LocalVariableInitializer:
    Single (value : Expression)
    Multiple (values : ArrayInitializer)
LocalConstantDeclaration = (`type` : Type, declarators : ConstantDeclarators)
StatementExpression = (value : Expression)
SwitchBlock = (sections : SwitchSections?)
SwitchSections = (items : [SwitchSection]+)
SwitchSection = (labels : SwitchLabels, statements : StatementList)
SwitchLabels = (items : [SwitchLabel]+)
SwitchLabel:
    Case (value : ConstantExpression)
    Default
ForInitializer:
    LocalVariableDeclaration (declaration : LocalVariableDeclaration)
    StatementExpressionList (expressions : StatementExpressionList)
ForCondition = (value : BooleanExpression)
ForIterator = (expressions : StatementExpressionList)
StatementExpressionList = (items : [StatementExpression]+)
CatchClauseList:
    AllSpecific (specific : SpecificCatchClauses)
    WithGeneral (specific : SpecificCatchClauses?, general : GeneralCatchClause)
SpecificCatchClauses = (items : [SpecificCatchClause]+)
SpecificCatchClause = (`type` : Type, name : Identifier?, body : Block)
GeneralCatchClause = (body : Block)
FinallyClause = (body : Block)
ResourceAcquisition:
    Declaration (declaration : LocalVariableDeclaration)
    Expression (expression : Expression)

# P504 B.2.6 Namespaces

CompilationUnit = (
    externAliases : ExternAliasDirectives?,
    usings : UsingDirectives?,
    `attributes` : GlobalAttributes?,
    members : NamespaceMemberDeclarations?
)
NamespaceDeclaration = (name : QualifiedIdentifier, body : NamespaceBody, hasTrailingSemicolon : bool?)
QualifiedIdentifier:
    Simple (name : Identifier)
    Compound (name : QualifiedIdentifier, member : Identifier)
NamespaceBody = (
    externAliases : ExternAliasDirectives?,
    usings : UsingDirectives?,
    members : NamespaceMemberDeclarations?
)
ExternAliasDirectives = (items : [ExternAliasDirective]+)
ExternAliasDirective = (name : Identifier)
UsingDirectives = (items : [UsingDirective]+)
UsingDirective:
    Alias (directive : UsingAliasDirective)
    Namespace (directive : UsingNamespaceDirective)
UsingAliasDirective = (alias : Identifier, name : NamespaceOrTypeName)
UsingNamespaceDirective = (name : NamespaceName)
NamespaceMemberDeclarations = (items : [NamespaceMemberDeclaration]+)
NamespaceMemberDeclaration:
    Namespace (declaration : NamespaceDeclaration)
    Type (declaration : TypeDeclaration)
TypeDeclaration:
    Class (declaration : ClassDeclaration)
    Struct (declaration : StructDeclaration)
    Interface (declaration : InterfaceDeclaration)
    Enum (declaration : EnumDeclaration)
    Delegate (declaration : DelegateDeclaration)
QualifiedAliasMember = (scope : Identifier, member : Identifier, typeArguments : TypeArgumentList?)

# P505 B.2.7 Classes

ClassDeclaration = (
    `attributes` : Attributes?,
    modifiers : ClassModifiers?,
    isPartial : bool,
    name : Identifier,
    typeParameters : TypeParameterList?,
    `base` : ClassBase?,
    constraints : TypeParameterConstraintsClauses?,
    body : ClassBody,
    hasTrailingSemicolon : bool?
)
ClassModifiers = (items : [ClassModifier]+)
ClassModifier:
    New
    Public
    Protected
    Internal
    Private
    Abstract
    Sealed
    Static
TypeParameterList = (parameters : TypeParameters)
TypeParameters = (items : [TypeParameter]+)
TypeParameter = (
    `attributes` : Attributes?,
    name : Identifier
)
ClassBase:
    ClassTypeOnly (`type` : ClassType)
    InterfaceTypeListOnly (types : InterfaceTypeList)
    ClassTypeAndInterfaceTypeList (`type` : ClassType, types : InterfaceTypeList)
InterfaceTypeList = (items : [InterfaceType]+)
TypeParameterConstraintsClauses = (items : [TypeParameterConstraintsClause]+)
TypeParameterConstraintsClause = (parameter : Identifier, constraints : TypeParameterConstraints)
TypeParameterConstraints:
    PrimaryConstraintOnly (primary : PrimaryConstraint)
    SecondaryConstraintsOnly (secondary : SecondaryConstraints)
    ConstructorConstraintOnly (constructor : ConstructorConstraint)
    PrimaryAndSecondaryConstraints (primary : PrimaryConstraint, secondary : SecondaryConstraints)
    PrimaryAndConstructorConstraints (primary : PrimaryConstraint, constructor : ConstructorConstraint)
    SecondaryAndConstructorConstraints (secondary : SecondaryConstraints, constructor : ConstructorConstraint)
    PrimarySecondaryAndConstructorConstraints (primary : PrimaryConstraint, secondary : SecondaryConstraints, constructor : ConstructorConstraint)
PrimaryConstraint:
    ClassType (`type` : ClassType)
    Class
    Struct
SecondaryConstraints = (items : [SecondaryConstraint]+)
SecondaryConstraint:
    InterfaceType (`type` : InterfaceType)
    TypeParameter (parameter : Identifier)
ConstructorConstraint = (unused : bool?) # TODO: fix this later
ClassBody = (declarations : ClassMemberDeclarations?)
ClassMemberDeclarations = (items : [ClassMemberDeclaration]+)
ClassMemberDeclaration:
    Constant (declaration : ConstantDeclaration)
    Field (declaration : FieldDeclaration)
    Method (declaration : MethodDeclaration)
    Property (declaration : PropertyDeclaration)
    Event (declaration : EventDeclaration)
    Indexer (declaration : IndexerDeclaration)
    Operator (declaration : OperatorDeclaration)
    Constructor (declaration : ConstructorDeclaration)
    Destructor (declaration : DestructorDeclaration)
    StaticConstructor (declaration : StaticConstructorDeclaration)
    Type (declaration : TypeDeclaration)
ConstantDeclaration = (
    `attributes` : Attributes?,
    modifiers : ConstantModifiers?,
    `type` : Type,
    declarators : ConstantDeclarators
)
ConstantModifiers = (items : [ConstantModifier]+)
ConstantModifier:
    New
    Public
    Protected
    Internal
    Private
ConstantDeclarators = (items : [ConstantDeclarator]+)
ConstantDeclarator = (name : Identifier, value : ConstantExpression)
FieldDeclaration = (
    `attributes` : Attributes?,
    modifiers : FieldModifiers?,
    `type` : Type,
    declarators : VariableDeclarators
)
FieldModifiers = (items : [FieldModifier]+)
FieldModifier:
    New
    Public
    Protected
    Internal
    Private
    Static
    Readonly
    Volatile
VariableDeclarators = (items : [VariableDeclarator]+)
VariableDeclarator = (name : Identifier, value : VariableInitializer?)
VariableInitializer:
    Single (value : Expression)
    Multiple (values : ArrayInitializer)
MethodDeclaration = (header : MethodHeader, body : MethodBody)
MethodHeader = (
    `attributes` : Attributes?,
    modifiers : MethodModifiers?,
    isPartial : bool,
    returnType : ReturnType,
    name : MemberName,
    typeParameters : TypeParameterList?,
    formalParameters : FormalParameterList?,
    constraints : TypeParameterConstraintsClauses?
)
MethodModifiers = (items : [MethodModifier]+)
MethodModifier:
    New
    Public
    Protected
    Internal
    Private
    Static
    Virtual
    Sealed
    Override
    Abstract
    Extern
    Async
ReturnType:
    Valued (`type` : Type)
    Void
MemberName:
    Simple (name : Identifier)
    Explicit (target : InterfaceType, name : Identifier)
MethodBody:
    Full (block : Block)
    Fast (value : Expression)
    Partial
FormalParameterList:
    FixedOnly (fixed : FixedParameters)
    ParamsOnly (params : ParameterArray)
    FixedAndParams (fixed : FixedParameters, params : ParameterArray)
FixedParameters = (items : [FixedParameter]+)
FixedParameter = (
    `attributes` : Attributes?,
    modifier : ParameterModifier?,
    `type` : Type,
    name : Identifier,
    `default` : DefaultArgument?
)
DefaultArgument = (value : Expression)
ParameterModifier:
    Ref
    Out
    This
ParameterArray = (
    `attributes` : Attributes?,
    `type` : ArrayType,
    name : Identifier
)
PropertyDeclaration = (
    `attributes` : Attributes?,
    modifiers : PropertyModifiers?,
    `type` : Type,
    name : MemberName,
    body : PropertyBody
)
PropertyModifiers = (items : [PropertyModifier]+)
PropertyModifier:
    New
    Public
    Protected
    Internal
    Private
    Static
    Virtual
    Sealed
    Override
    Abstract
    Extern
PropertyBody:
    Full (accessors : AccessorDeclarations, initializer : PropertyInitializer?)
    Fast (value : Expression)
PropertyInitializer = (value : VariableInitializer)
AccessorDeclarations:
    GetOnly (getter : GetAccessorDeclaration)
    SetOnly (setter : SetAccessorDeclaration)
    GetSet (getter : GetAccessorDeclaration, setter : SetAccessorDeclaration)
    SetGet (setter : SetAccessorDeclaration, getter : GetAccessorDeclaration)
GetAccessorDeclaration = (`attributes` : Attributes?, modifier : AccessorModifier?, body : AccessorBody)
SetAccessorDeclaration = (`attributes` : Attributes?, modifier : AccessorModifier?, body : AccessorBody)
AccessorModifier:
    Protected
    Internal
    Private
    ProtectedInternal
    InternalProtected
AccessorBody:
    Full (block : Block)
    Partial
EventDeclaration:
    Auto (`attributes` : Attributes?, modifiers : EventModifiers?, `type` : Type, declarators : VariableDeclarators)
    Explicit (`attributes` : Attributes?, modifiers : EventModifiers?, `type` : Type, name : MemberName, accessors : EventAccessorDeclarations)
EventModifiers = (items : [EventModifier]+)
EventModifier:
    New
    Public
    Protected
    Internal
    Private
    Static
    Virtual
    Sealed
    Override
    Abstract
    Extern
EventAccessorDeclarations:
    AddOnly (`add` : AddAccessorDeclaration)
    RemoveOnly (`remove` : RemoveAccessorDeclaration)
    AddRemove (`add` : AddAccessorDeclaration, `remove` : RemoveAccessorDeclaration)
    RemoveAdd (`remove` : RemoveAccessorDeclaration, `add` : AddAccessorDeclaration)
AddAccessorDeclaration = (`attributes` : Attributes?, block : Block)
RemoveAccessorDeclaration = (`attributes` : Attributes?, block : Block)
IndexerDeclaration = (
    `attributes` : Attributes?,
    modifiers : IndexerModifiers?,
    declarator : IndexerDeclarator,
    body : IndexerBody
)
IndexerModifiers = (items : [IndexerModifier]+)
IndexerModifier:
    New
    Public
    Protected
    Internal
    Private
    Virtual
    Sealed
    Override
    Abstract
    Extern
IndexerDeclarator:
    Simple (`type` : Type, formalParameters : FormalParameterList)
    Explicit (`type` : Type, target : InterfaceType, formalParameters : FormalParameterList)
IndexerBody:
    Full (accessors : AccessorDeclarations)
    Fast (value : Expression)
OperatorDeclaration = (
    `attributes` : Attributes?,
    modifiers : OperatorModifiers,
    declarator : OperatorDeclarator,
    body : OperatorBody
)
OperatorModifiers = (items : [OperatorModifier]+)
OperatorModifier:
    Public
    Static
    Extern
OperatorDeclarator:
    Unary (resultType : Type, operator : OverloadableUnaryOperator, parameterType : Type, parameterName : Identifier)
    Binary (resultType : Type, operator : OverloadableBinaryOperator, leftType : Type, leftName : Identifier, rightType : Type, rightName : Identifier)
    Conversion:
        ImplicitConversion (resultType : Type, parameterType : Type, parameterName : Identifier)
        ExplicitConversion (resultType : Type, parameterType : Type, parameterName : Identifier)
OverloadableUnaryOperator:
    Positive
    Negative
    LogicalNot
    BitwiseNot
    Increment
    Decrement
    `True`
    `False`
OverloadableBinaryOperator:
    Multiply
    Divide
    Modulo
    Add
    Subtract
    LeftShift
    RightShift
    LessThan
    GreaterThan
    LessEqual
    GreaterEqual
    EqualTo
    NotEqualTo
    BitwiseAnd
    BitwiseXor
    BitwiseOr
OperatorBody:
    Full (block : Block)
    Fast (value : Expression)
    Partial
ConstructorDeclaration = (
    `attributes` : Attributes?,
    modifiers : ConstructorModifiers?,
    declarator : ConstructorDeclarator,
    body : ConstructorBody
)
ConstructorModifiers = (items : [ConstructorModifier]+)
ConstructorModifier:
    Public
    Protected
    Internal
    Private
    Extern
ConstructorDeclarator = (
    name : Identifier,
    formalParameters : FormalParameterList?,
    initializer : ConstructorInitializer?
)
ConstructorInitializer:
    Base (arguments : ArgumentList?)
    This (arguments : ArgumentList?)
ConstructorBody:
    Full (block : Block)
    Partial
StaticConstructorDeclaration = (
    `attributes` : Attributes?,
    modifiers : StaticConstructorModifiers,
    name : Identifier,
    body : StaticConstructorBody
)
StaticConstructorModifiers:
    ExternStatic (isExtern : bool)
    StaticExtern (isExtern : bool)
StaticConstructorBody:
    Full (block : Block)
    Partial
DestructorDeclaration = (
    `attributes` : Attributes?,
    isExtern : bool,
    name : Identifier,
    body : DestructorBody
)
DestructorBody:
    Full (block : Block)
    Partial

# P512 B.2.8 Structs

StructDeclaration = (
    `attributes` : Attributes?,
    modifiers : StructModifiers?,
    isPartial : bool,
    name : Identifier,
    typeParameters : TypeParameterList?,
    interfaces : StructInterfaces?,
    constraints : TypeParameterConstraintsClauses?,
    body : StructBody,
    hasTrailingSemicolon : bool?
)
StructModifiers = (items : [StructModifier]+)
StructModifier:
    New
    Public
    Protected
    Internal
    Private
StructInterfaces = (types : InterfaceTypeList)
StructBody = (declarations : StructMemberDeclarations?)
StructMemberDeclarations = (items : [StructMemberDeclaration]+)
StructMemberDeclaration:
    Constant (declaration : ConstantDeclaration)
    Field (declaration : FieldDeclaration)
    Method (declaration : MethodDeclaration)
    Property (declaration : PropertyDeclaration)
    Event (declaration : EventDeclaration)
    Indexer (declaration : IndexerDeclaration)
    Operator (declaration : OperatorDeclaration)
    Constructor (declaration : ConstructorDeclaration)
    StaticConstructor (declaration : StaticConstructorDeclaration)
    Type (declaration : TypeDeclaration)

# P513 B.2.9 Arrays

RankSpecifiers = (items : [RankSpecifier]+)
RankSpecifier = (rank : int+)
ArrayInitializer = (variableInitializers : VariableInitializerList?, hasTrailingComma : bool?)
VariableInitializerList = (items : [VariableInitializer]+)

# P513 B.2.10 Interfaces

InterfaceDeclaration = (
    `attributes` : Attributes?,
    modifiers : InterfaceModifiers?,
    isPartial : bool,
    name : Identifier,
    typeParameters : VariantTypeParameterList?,
    `base` : InterfaceBase?,
    constraints : TypeParameterConstraintsClauses?,
    body : InterfaceBody,
    hasTrailingSemicolon : bool?
)
InterfaceModifiers = (items : [InterfaceModifier]+)
InterfaceModifier:
    New
    Public
    Protected
    Internal
    Private
VariantTypeParameterList = (parameters : VariantTypeParameters)
VariantTypeParameters = (items : [VariantTypeParameter]+)
VariantTypeParameter = (
    `attributes` : Attributes?,
    annotation : VarianceAnnotation?,
    name : Identifier
)
VarianceAnnotation:
    In
    Out
InterfaceBase = (types : InterfaceTypeList)
InterfaceBody = (declarations : InterfaceMemberDeclarations?)
InterfaceMemberDeclarations = (items : [InterfaceMemberDeclaration]+)
InterfaceMemberDeclaration:
    Method (declaration : InterfaceMethodDeclaration)
    Property (declaration : InterfacePropertyDeclaration)
    Event (declaration : InterfaceEventDeclaration)
    Indexer (declaration : InterfaceIndexerDeclaration)
InterfaceMethodDeclaration = (
    `attributes` : Attributes?,
    isNew : bool,
    returnType : ReturnType,
    name : Identifier,
    typeParameters : VariantTypeParameterList?,
    formalParameters : FormalParameterList?,
    constraints : TypeParameterConstraintsClauses?
)
InterfacePropertyDeclaration = (
    `attributes` : Attributes?,
    isNew : bool,
    `type` : Type,
    name : Identifier,
    accessors : InterfaceAccessors
)
InterfaceAccessors:
    GetOnly (getter : InterfaceGetAccessor)
    SetOnly (setter : InterfaceSetAccessor)
    GetSet (getter : InterfaceGetAccessor, setter : InterfaceSetAccessor)
    SetGet (setter : InterfaceSetAccessor, getter : InterfaceGetAccessor)
InterfaceGetAccessor = (`attributes` : Attributes?)
InterfaceSetAccessor = (`attributes` : Attributes?)
InterfaceEventDeclaration = (
    `attributes` : Attributes?,
    isNew : bool,
    `type` : Type,
    name : Identifier
)
InterfaceIndexerDeclaration = (
    `attributes` : Attributes?,
    isNew : bool,
    `type` : Type,
    formalParameters : FormalParameterList,
    accessors : InterfaceAccessors
)

# P514 B.2.11 Enums

EnumDeclaration = (
    `attributes` : Attributes?,
    modifiers : EnumModifiers?,
    name : Identifier,
    `base` : EnumBase?,
    body : EnumBody,
    hasTrailingSemicolon : bool?
)
EnumBase = (`type` : IntegralType)
EnumBody = (declarations : EnumMemberDeclarations?, hasTrailingComma : bool?)
EnumModifiers = (items : [EnumModifier]+)
EnumModifier:
    New
    Public
    Protected
    Internal
    Private
EnumMemberDeclarations = (items : [EnumMemberDeclaration]+)
EnumMemberDeclaration = (`attributes` : Attributes?, name : Identifier, value : ConstantExpression?)

# P515 B.2.12 Delegates

DelegateDeclaration = (
    `attributes` : Attributes?,
    modifiers : DelegateModifiers?,
    returnType : ReturnType,
    name : Identifier,
    typeParameters : VariantTypeParameterList?,
    formalParameters : FormalParameterList?,
    constraints : TypeParameterConstraintsClauses?
)
DelegateModifiers = (items : [DelegateModifier]+)
DelegateModifier:
    New
    Public
    Protected
    Internal
    Private

# P515 B.2.13 Attributes

GlobalAttributes = (sections : GlobalAttributeSections)
GlobalAttributeSections = (items : [GlobalAttributeSection]+)
GlobalAttributeSection = (specifier : GlobalAttributeTargetSpecifier, `attributes` : AttributeList, hasTrailingComma : bool?)
GlobalAttributeTargetSpecifier = (target : GlobalAttributeTarget)
GlobalAttributeTarget:
    Assembly
    Module
Attributes = (sections : AttributeSections)
AttributeSections = (items : [AttributeSection]+)
AttributeSection = (specifier : AttributeTargetSpecifier?, `attributes` : AttributeList, hasTrailingComma : bool?)
AttributeTargetSpecifier = (target : AttributeTarget)
AttributeTarget:
    Field
    Event
    Method
    Param
    Property
    Return
    Type
AttributeList = (items : [Attribute]+)
Attribute = (name : AttributeName, arguments : AttributeArguments?)
AttributeName = (`type` : TypeName)
AttributeArguments = (positional : PositionalArgumentList?, named : NamedArgumentList?)
PositionalArgumentList = (items : [PositionalArgument]+)
PositionalArgument = (name : ArgumentName?, value : AttributeArgumentExpression)
NamedArgumentList = (items : [NamedArgument]+)
NamedArgument = (name : Identifier, value : AttributeArgumentExpression)
AttributeArgumentExpression = (value : Expression)

%%

Expression as Expression:
    pass
